package net.bithappens.hnqe.mapper.graphxml;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Timer;

import net.bithappens.hnqe.cache.ICacheManipulate;
import net.bithappens.hnqe.mapper.IMapper;
import net.bithappens.hnqe.query.QueryTree;

import org.apache.log4j.Logger;

public class GraphMapper implements IMapper{

	private Logger log = Logger.getLogger(this.getClass());
	
	private PropertyBean properties;
	
	private ICacheManipulate cache;
	
	private Collection<Timer> timers = new ArrayList<Timer>();
	
	private Map<String,Map<String, Date>> fetchTime = new HashMap<String, Map<String, Date>>();

	
	public GraphMapper() throws Exception{
		
		log.info("Setting up XMLGraph");
		
		properties = PropertyLoader.loadProperties();

	}
	
	@Override
	public void setCache(ICacheManipulate cache) {
		this.cache = cache;		
	}

	@Override
	public Collection<String> getInstanceIds() {
		Collection<String> instanceIds = new HashSet<String>();
		for(InstanceConfigBean instanceConfig : properties.getInstanceConfigs()){
			instanceIds.add(instanceConfig.getInstanceId());	
		}
		return instanceIds;
	}
	
	@Override
	public String getMapperId() {
		return properties.getMapperId();
	}

	@Override
	public boolean fetch(String instanceId, QueryTree query) {

		log.info("Performing lazy load");

		Collection<InstanceConfigBean> configs = properties.getConfigsForInstance(instanceId);
		
		if(configs == null){
			return false;
		}
				
		boolean shouldReload = false;
		
		Map<String, Date> timeStamps = fetchTime.get(instanceId);
		
		for(InstanceConfigBean config : configs){
			
			XMLGraphDataParser graphParser = null;
			if(timeStamps != null){
				graphParser = new XMLGraphDataParser(config.getSourcePath(), timeStamps.get(config.getSourcePath()));	
			} else {
				graphParser = new XMLGraphDataParser(config.getSourcePath());
			}
						
			try {
				
				if(graphParser.getNodesToWrite() != null && graphParser.getNodesToWrite().size() > 0){
					
					cache.pushNodes(instanceId, graphParser.getNodesToWrite(), config.getInstructions());
					
					shouldReload = true;
				}
				
			} catch (Exception e) {
				log.error("Graph nodes couldn't be written due to: "+e.getMessage(), e);
			}

			try {

				if(graphParser.getRelationsToWrite() != null && graphParser.getRelationsToWrite().size() > 0){
					cache.pushNodes(instanceId, graphParser.getNodesToWrite(), config.getInstructions());
					
					shouldReload = true;
				}

			} catch (Exception e) {
				log.error("Graph relations couldn't be written due to: "+e.getMessage(), e);
			}

			if(timeStamps == null){
				timeStamps = new HashMap<String, Date>();
				fetchTime.put(instanceId, timeStamps);
			}
			
			timeStamps.put(config.getSourcePath(), graphParser.getXmlDataTimeStamp());
		}
		
		return shouldReload;
	}

	
	
	@Override
	public void start() {

		if(cache == null){
			log.error("There is no cache set. Terminating thread");
			return;
		}
		
		for(InstanceConfigBean instanceConfig : properties.getInstanceConfigs()){
			
			XMLGraphDataParser graphParser = new XMLGraphDataParser(instanceConfig.getSourcePath());
			
			Timer timer = new Timer();
			timer.schedule(
					new CronJob(instanceConfig.getInstanceId(), cache, instanceConfig.getInstructions(), graphParser), 
					0L, instanceConfig.getRefreshIntervall()
				);			
			timers.add(timer);
		}
		
		log.info("XMLGraph Mapper started");
		
	}

	@Override
	public void stop() {
		for(Timer timer : timers){
			timer.cancel();
		}
	}
	
}
